﻿using Newtonsoft.Json.Linq;
using Stock.Client.Utils;
using Stock.Dao;
using Stock.Model.DB;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Stock.Client.Service
{
      public class Tencent_Service
      {

            #region 公共方法

            /// <summary>
            /// 从腾讯API获取数据
            /// </summary>
            /// <returns></returns>
            public static async Task<string> GetApiDataAsync()
            {
                  string url = ConfigurationManager.AppSettings["TENCENT"].ToString();
                  //获取代码，并拼接
                  string doces = BaseDao.GetCodes(true);
                  if (string.IsNullOrEmpty(doces))
                  {
                        return "";
                  }
                  //获取实时报价
                  string data = await HttpUtils.GetSendAsync(url, doces);
                  return data;
            }

            /// <summary>
            /// 根据代码获取名称
            /// </summary>
            /// <param name="code"></param>
            /// <returns></returns>
            public static async Task<string> GetStockBaseInfoAsync(string code)
            {
                  string url = ConfigurationManager.AppSettings["TENCENT"].ToString();
                  string data = await HttpUtils.GetSendAsync(url, code);
                  return data;
            }





            #endregion

            #region TStockLog

            /// <summary>
            /// 保存当前数据
            /// </summary>
            /// <param name="stockLog"></param>
            /// <returns></returns>
            public static bool InsertStockLog(TStockLog stockLog)
            {
                  return TencentDao.Insert<TStockLog>(stockLog);
            }

            /// <summary>
            /// 清空分时价格
            /// </summary>
            public static void ClearStockLog()
            {
                  TencentDao.ClearStockLog();
            }


            /// <summary>
            /// 获得当前报价
            /// </summary>
            /// <param name="code"></param>
            /// <returns></returns>
            public static TStockLog GetCurrentStockPrice(string code)
            {
                  TStockLog stockLog = TencentDao.GetCurrentStockPrice(code);
                  return stockLog;
            }

            /// <summary>
            /// 获取最新价格
            /// </summary>
            /// <param name="codes"></param>
            /// <returns></returns>
            public static IList<TStockLog> GetCurrentStocksPrice(string codes)
            {
                  string result = DateUtils.GetStockSingleInfo(codes);
                  string[] stocks = result.Split(';');
                  List<TStockLog> stockLogs = new List<TStockLog>();
                  for (int i = 0; i < stocks.Length; i++)
                  {
                        string[] stock = stocks[i].Split('~');
                        if (stock.Length < 11)
                              continue;
                        TStockLog stockLog = new TStockLog()
                        {
                              CODE = stock[2],
                              NAME = stock[1],
                              CLOSE = Convert.ToDecimal(stock[3])
                        };
                        stockLogs.Add(stockLog);
                  }

                  return stockLogs;
                  //[0]: "v_s_sz300441=\"51"
                  //[1]: "鲍斯股份"
                  //[2]: "300441"
                  //[3]: "11.41"   C
                  //[4]: "-0.26"    涨跌
                  //[5]: "-2.23"    涨跌%
                  //[6]: "126223"   成交量
                  //[7]: "14516"    成交额
                  //[8]: ""
                  //[9]: "74.99"
                  //[10]: "GP-A-CYB\""
            }

            #endregion

            #region TStock

            public static TStock GetStockByCode(string code)
            {
                  return TencentDao.GetStockByCode(code);
            }

            /// <summary>
            /// 更新
            /// </summary>
            /// <param name="id"></param>
            /// <param name="isTrading"></param>
            /// <param name="isAlert"></param>
            /// <param name="isWXAlert"></param>
            /// <returns></returns>
            public static bool UpdateStock(int id, bool isTrading, bool isAlert, bool isWXAlert, string remark)
            {
                  return TencentDao.UpdateStock(id, isTrading, isAlert, isWXAlert, remark);
            }

            /// <summary>
            /// 删除
            /// </summary>
            /// <param name="id"></param>
            /// <returns></returns>
            public static bool DelStock(int id)
            {
                  return TencentDao.DelStock(id);
            }


            /// <summary>
            /// 新增
            /// </summary>
            /// <param name="stock"></param>
            /// <returns></returns>
            public static bool InsertStock(TStock stock)
            {
                  return TencentDao.Insert<TStock>(stock);
            }

            /// <summary>
            /// 获取需要监控的STOCK列表
            /// </summary>
            /// <returns></returns>
            public static IList<TStock> GetStockList()
            {
                  IList<TStock> dataTable = TencentDao.GetStockList();
                  return dataTable;
            }



            #endregion

            #region 通道

            public static TStockChannel GetStockChannel(int id)
            {
                  string sql = string.Format("SELECT * FROM [T_STOCK_CHANNEL] WHERE [ID] = {0}", id);
                  return TencentDao.GetObject<TStockChannel>(sql);
            }

            public static IList<TStockChannel> GetStockChannels()
            {
                  return TencentDao.GetStockChannels();
            }

            public static bool InsertChannel(TStockChannel stockChannel)
            {
                  return TencentDao.InsertChannel(stockChannel);
            }

            public static bool DelChannel(int id)
            {
                  string sql = string.Format("DELETE FROM [T_STOCK_CHANNEL] WHERE [ID] = {0}", id);
                  return BaseDao.Delete(sql);
            }

            public static bool UpdateChannel(TStockChannel stockChannel)
            {
                  stockChannel.DATE_INTERVAL = GetHolidaysCount(stockChannel.POINT_A_DATE, stockChannel.POINT_C_DATE, diffResultFormat.dd);
                  return BaseDao.Update<TStockChannel>(stockChannel);
            }

            #endregion

            #region 箱体

            public static TStockEnclosure GetStockEnclosure(int id)
            {
                  string sql = string.Format("SELECT * FROM [T_STOCK_ENCLOSURE] WHERE [ID] = {0}", id);
                  return TencentDao.GetObject<TStockEnclosure>(sql);
            }

            public static IList<TStockEnclosure> GetStockEnclosures()
            {
                  return TencentDao.GetStockEnclosure();
            }

            public static bool InsertEnclosure(TStockEnclosure stockEnclosure)
            {
                  return TencentDao.InsertEnclosure(stockEnclosure);
            }

            public static bool UpdateEnclosure(TStockEnclosure stockEnclosure)
            {
                  return BaseDao.Update<TStockEnclosure>(stockEnclosure);
            }

            public static bool DelEnclosure(int id)
            {
                  string sql = string.Format("DELETE FROM [T_STOCK_ENCLOSURE] WHERE [ID] = {0}", id);
                  return BaseDao.Delete(sql);
            }


            #endregion

            #region 三角

            public static TStockTriangle GetStockTriangle(int id)
            {
                  string sql = string.Format("SELECT * FROM [T_STOCK_TRIANGLE] WHERE [ID] = {0}", id);
                  return TencentDao.GetObject<TStockTriangle>(sql);
            }

            public static IList<TStockTriangle> GetStockTriangles()
            {
                  return TencentDao.GetStockTriangle();
            }



            public static bool InsertTriangle(TStockTriangle stockTriangle)
            {
                  return TencentDao.InsertTriangle(stockTriangle);
            }

            public static bool UpdateTriangle(TStockTriangle stockTriangle)
            {
                  return BaseDao.Update<TStockTriangle>(stockTriangle);
            }

            public static bool DelTriangle(int id)
            {
                  string sql = string.Format("DELETE FROM [T_STOCK_TRIANGLE] WHERE [ID] = {0}", id);
                  return BaseDao.Delete(sql);
            }



            #endregion

            #region 历史数据

            public static bool InsertTStockHistory(IList<TStockHistory> stockHistorys)
            {
                  return TencentDao.InsertTStockHistory(stockHistorys);
            }


            public static IList<TStockHistory> GetTStockHistory(string value, string code, string name, string fq = "qfqday")
            {
                  JObject keyValuePairs = JObject.Parse(value);
                  int len = keyValuePairs["data"][code]["qfqday"].Count();
                  List<TStockHistory> stockHistorys = new List<TStockHistory>();
                  for (int i = 0; i < len; i++)
                  {
                        TStockHistory stockHistory = new TStockHistory()
                        {
                              TRADING_DATE = Convert.ToDateTime(keyValuePairs["data"][code][fq][i][0]),
                              OPEN = Convert.ToDecimal(keyValuePairs["data"][code][fq][i][1]),
                              CLOSE = Convert.ToDecimal(keyValuePairs["data"][code][fq][i][2]),
                              HIGH = Convert.ToDecimal(keyValuePairs["data"][code][fq][i][3]),
                              LOW = Convert.ToDecimal(keyValuePairs["data"][code][fq][i][4]),
                              VOL = Convert.ToDecimal(keyValuePairs["data"][code][fq][i][5]),
                              CODE = code,
                              NAME = name,
                              JSON = value
                        };
                        stockHistorys.Add(stockHistory);
                  }
                  InsertTStockHistory(stockHistorys);
                  return stockHistorys;
            }

            #endregion

            #region 交易计划

            /// <summary>
            /// 交易计划设置为已提醒
            /// </summary>
            /// <param name="id"></param>
            public static void UpdateStockSchedule(int id)
            {
                  TencentDao.UpdateStockSchedule(id);
            }

            /// <summary>
            /// 获取今日的操作计划
            /// </summary>
            /// <returns></returns>
            public static IList<TStockSchedule> GetStockSchedule(string code = "")
            {
                  return TencentDao.GetStockSchedule(code);
            }

            /// <summary>
            /// 创建当日交易计划
            /// </summary>
            public static void InsertStockSchedule()
            {
                  //通道模型T_STOCK_CHANNEL
                  InsertChannelModel();

                  //箱体模型T_STOCK_ENCLOSURE
                  InsertEnclosureModel();

                  //三角模型T_STOCK_TRIANGLE
                  InsertTriangleModel();
            }

            /// <summary>
            /// 通道模型T_STOCK_CHANNEL
            /// </summary>
            private static void InsertChannelModel()
            {
                  IList<TStockChannel> stockChannels = TencentDao.GetStockChannels();
                  List<TStockSchedule> stockSchedules = new List<TStockSchedule>();
                  decimal slope = 0;
                  int intervalUp = 0, intervalDown = 0;
                  foreach (TStockChannel stockChannel in stockChannels)
                  {
                        //slope斜率
                        slope = Math.Abs(stockChannel.POINT_A - stockChannel.POINT_C) / (stockChannel.DATE_INTERVAL);
                        //当日和基准日相差多少交易日

                        intervalUp = GetHolidaysCount(stockChannel.POINT_A_DATE, DateTime.Now, diffResultFormat.dd) - 2;
                        intervalDown = GetHolidaysCount(stockChannel.POINT_B_DATE, DateTime.Now, diffResultFormat.dd) - 2;
                        decimal salePrice = slope * intervalUp + stockChannel.POINT_A;
                        decimal buyPrice = slope * intervalDown + stockChannel.POINT_B;
                        TStockSchedule stockSchedule = new TStockSchedule()
                        {
                              CODE = stockChannel.CODE,
                              NAME = stockChannel.NAME,
                              IS_REAL_TRADING = true,
                              PREFIX = PublicUtils.GetPrefix(stockChannel.CODE),
                              PRICE = buyPrice > salePrice ? salePrice : buyPrice,
                              SCHEDULE_DATE = DateTime.Now,
                              TRADING = "B"
                        };
                        stockSchedules.Add(stockSchedule);

                        stockSchedule = new TStockSchedule()
                        {
                              CODE = stockChannel.CODE,
                              NAME = stockChannel.NAME,
                              IS_REAL_TRADING = true,
                              PREFIX = PublicUtils.GetPrefix(stockChannel.CODE),
                              PRICE = salePrice > buyPrice ? salePrice : buyPrice,
                              SCHEDULE_DATE = DateTime.Now,
                              TRADING = "S"
                        };
                        stockSchedules.Add(stockSchedule);
                  }
                  TencentDao.SaveSchedule(stockSchedules);
            }


            /// <summary>
            /// 保存箱体模型T_STOCK_ENCLOSURE
            /// </summary>
            private static void InsertEnclosureModel()
            {
                  IList<TStockEnclosure> stockEnclosures = TencentDao.GetStockEnclosure();
                  List<TStockSchedule> stockSchedules = new List<TStockSchedule>();
                  foreach (TStockEnclosure stockEnclosure in stockEnclosures)
                  {
                        TStockSchedule stockSchedule = new TStockSchedule()
                        {
                              CODE = stockEnclosure.CODE,
                              NAME = stockEnclosure.NAME,
                              IS_REAL_TRADING = true,
                              PREFIX = PublicUtils.GetPrefix(stockEnclosure.CODE),
                              PRICE = stockEnclosure.POINT_UP,
                              SCHEDULE_DATE = DateTime.Now,
                              TRADING = "S"
                        };
                        stockSchedules.Add(stockSchedule);

                        stockSchedule = new TStockSchedule()
                        {
                              CODE = stockEnclosure.CODE,
                              NAME = stockEnclosure.NAME,
                              IS_REAL_TRADING = true,
                              PREFIX = PublicUtils.GetPrefix(stockEnclosure.CODE),
                              PRICE = stockEnclosure.POINT_DOWN,
                              SCHEDULE_DATE = DateTime.Now,
                              TRADING = "B"
                        };
                        stockSchedules.Add(stockSchedule);
                  }

                  TencentDao.SaveSchedule(stockSchedules);
            }

            /// <summary>
            /// 三角模型T_STOCK_TRIANGLE
            /// </summary>
            private static void InsertTriangleModel()
            {
                  IList<TStockTriangle> stockTriangles = TencentDao.GetStockTriangle();
                  List<TStockSchedule> stockSchedules = new List<TStockSchedule>();
                  decimal slopeUp = 0, slopeDown = 0;

                  foreach (TStockTriangle stockTriangle in stockTriangles)
                  {
                        //slope斜率
                        slopeUp = Math.Abs(stockTriangle.POINT_UP_A1 - stockTriangle.POINT_UP_A2) /
                              GetHolidaysCount(stockTriangle.POINT_UP_A1_DATE, stockTriangle.POINT_UP_A2_DATE, diffResultFormat.dd);
                        slopeDown = Math.Abs(stockTriangle.POINT_DOWN_A1 - stockTriangle.POINT_DOWN_A2)
                              / GetHolidaysCount(stockTriangle.POINT_DOWN_A1_DATE, stockTriangle.POINT_DOWN_A2_DATE, diffResultFormat.dd);
                        //当日和基准日相差多少交易日
                        int intervalUp = GetHolidaysCount(stockTriangle.POINT_UP_A1_DATE, DateTime.Now, diffResultFormat.dd) - 2;
                        int intervalDown = GetHolidaysCount(stockTriangle.POINT_DOWN_A1_DATE, DateTime.Now, diffResultFormat.dd) - 2;
                        decimal salePrice = slopeUp * intervalUp + stockTriangle.POINT_UP_A1;
                        decimal buyPrice = slopeDown * intervalDown + stockTriangle.POINT_DOWN_A1;

                        TStockSchedule stockSchedule = new TStockSchedule()
                        {
                              CODE = stockTriangle.CODE,
                              NAME = stockTriangle.NAME,
                              IS_REAL_TRADING = true,
                              PREFIX = PublicUtils.GetPrefix(stockTriangle.CODE),
                              PRICE = salePrice,
                              SCHEDULE_DATE = DateTime.Now,
                              TRADING = "S"
                        };
                        stockSchedules.Add(stockSchedule);

                        stockSchedule = new TStockSchedule()
                        {
                              CODE = stockTriangle.CODE,
                              NAME = stockTriangle.NAME,
                              IS_REAL_TRADING = true,
                              PREFIX = PublicUtils.GetPrefix(stockTriangle.CODE),
                              PRICE = buyPrice,
                              SCHEDULE_DATE = DateTime.Now,
                              TRADING = "B"
                        };
                        stockSchedules.Add(stockSchedule);

                  }

            }

            private static void DelStockSchedule(int id)
            {
                  
            }

            private static void DelStockSchedule(TStockSchedule stockSchedule)
            {
                  DelStockSchedule(stockSchedule.ID);
            }

            #endregion

            #region 监控

            /// <summary>
            /// 
            /// </summary>
            /// <param name="code"></param>
            /// <param name="p">当前价格</param>
            //public static List<string> GetMonitorStockResult(string code, decimal p)
            //{
            //      List<string> msg = new List<string>();

            //      msg.AddRange(GetMonitorEnclosure(code, p));
            //      msg.AddRange(GetMonitorChannel(code, p));
            //      msg.AddRange(GetMonitorTriangle(code, p));

            //      return msg;
            //}

            /// <summary>
            /// 箱体模型
            /// </summary>
            /// <param name="code"></param>
            /// <param name="p"></param>
            //public static List<string> GetMonitorEnclosure(string code, decimal p)
            //{
            //      List<string> msg = new List<string>();
            //      IList<TStockEnclosure> stockEnclosures = GetEnclosureModel(code);
            //      foreach (TStockEnclosure stockEnclosure in stockEnclosures)
            //      {
            //            if (p >= stockEnclosure.POINT_UP)
            //            {
            //                  msg.Add(string.Format("{0} {1} 触发了卖出预警 {2} 。", stockEnclosure.CODE, stockEnclosure.NAME, stockEnclosure.POINT_UP));
            //            }
            //            if (p <= stockEnclosure.POINT_DOWN)
            //            {
            //                  msg.Add(string.Format("{0} {1} 触发了买入预警 {2} 。", stockEnclosure.CODE, stockEnclosure.NAME, stockEnclosure.POINT_DOWN));
            //            }
            //      }
            //      return msg;
            //}

            //public static List<string> GetMonitorChannel(string code, decimal p)
            //{
            //      List<string> msg = new List<string>();
            //      return msg;
            //}

            //public static List<string> GetMonitorTriangle(string code, decimal p)
            //{
            //      List<string> msg = new List<string>();
            //      return msg;

            //}





            #endregion

            #region 节假日


            /// <summary>
            /// 计算2个日期的间隔单位数，包含边界值
            /// </summary>
            /// <param name="s"></param>
            /// <param name="e"></param>
            /// <param name="diffResultFormat"></param>
            public static int GetHolidaysCount(DateTime s, DateTime e, diffResultFormat diffResultFormat)
            {
                  int year = 0, month = 0;
                  int old_year = 0, old_month = 0;
                  int interval = 0;
                  int m = 0;
                  int poor = 0;//时间差
                  DateTime s1 = s;
                  List<THoliday> holidays = new List<THoliday>();
                  poor = toResult(s, e, diffResultFormat)[0] + 1;
                  for (int i = 0; i < poor; i++)
                  {
                        year = s1.Year;
                        month = s1.Month;
                        if (old_year == year && old_month == month)
                        {
                              s1 = s1.AddDays(1);
                              continue;
                        }
                        else
                        {
                              old_year = year = s1.Year;
                              old_month = month = s1.Month;
                              m = TencentDao.GetHolidays(year, month);
                              if (m == 0)//
                              {
                                    _ = DateUtils.GetHolidays(year.ToString(), month.ToString());
                              }
                              holidays.AddRange(TencentDao.GetHolidayList(year, month));
                        }
                  }
                  foreach (THoliday holiday in holidays)
                  {
                        if (Convert.ToDateTime(holiday.HOLIDAY.ToShortDateString()) >= s.AddDays(-1)
                              && Convert.ToDateTime(holiday.HOLIDAY.ToShortDateString()) <= e.AddDays(1))
                              interval++;
                  }

                  return interval;
            }


            /// <summary>
            /// 计算日期间隔
            /// </summary>
            /// <param name="d1">要参与计算的其中一个日期</param>
            /// <param name="d2">要参与计算的另一个日期</param>
            /// <param name="drf">决定返回值形式的枚举</param>
            /// <returns>一个代表年月日的int数组，具体数组长度与枚举参数drf有关</returns>
            public static int[] toResult(DateTime d1, DateTime d2, diffResultFormat drf)
            {
                  #region 数据初始化
                  DateTime max;
                  DateTime min;
                  int year;
                  int month;
                  int tempYear, tempMonth;
                  if (d1 > d2)
                  {
                        max = d1;
                        min = d2;
                  }
                  else
                  {
                        max = d2;
                        min = d1;
                  }
                  tempYear = max.Year;
                  tempMonth = max.Month;
                  if (max.Month < min.Month)
                  {
                        tempYear--;
                        tempMonth = tempMonth + 12;
                  }
                  year = tempYear - min.Year;
                  month = tempMonth - min.Month;
                  #endregion
                  #region 按条件计算
                  if (drf == diffResultFormat.dd)
                  {
                        TimeSpan ts = max - min;
                        return new int[] { ts.Days };
                  }
                  if (drf == diffResultFormat.mm)
                  {
                        return new int[] { month + year * 12 };
                  }
                  if (drf == diffResultFormat.yy)
                  {
                        return new int[] { year };
                  }
                  return new int[] { year, month };
                  #endregion
            }

            /// <summary>
            /// 关于返回值形式的枚举
            /// </summary>
            public enum diffResultFormat
            {
                  /// <summary>
                  /// 年数和月数
                  /// </summary>
                  yymm,
                  /// <summary>
                  /// 年数
                  /// </summary>
                  yy,
                  /// <summary>
                  /// 月数
                  /// </summary>
                  mm,
                  /// <summary>
                  /// 天数
                  /// </summary>
                  dd,
            }



            #endregion
      }
}
